#!/usr/bin/env python

import argparse
import logging
import time
import hmac
import hashlib
import base64
import urllib.parse
import requests
import json
import os
import math
import sys
import asyncio
sys.path.append('..')
from crypto.crypto_analyzer import CryptoAnalyzer
from dingtalk_robot import DingTalkRobot

# 常量定义
SIGNAL_STRENGTH_THRESHOLDS = {
    'STRONG': 2.0,   # 成交量是平均值的2倍及以上
    'MEDIUM': 1.5,   # 成交量是平均值的1.5倍及以上
    'WEAK': 1.1      # 成交量是平均值的1.1倍及以上
}

SYMBOL = 'BTCUSDT'
INTERVALS = ['1m', '5m', '10m', '30m', '1h']

# 添加全局变量来跟踪最后一次@所有人的发送时间
global last_at_all_time
last_at_all_time = 0

def load_signal_history_from_file():
    """从文件加载信号历史记录"""
    signal_history = []
    try:
        # 确保目录存在
        os.makedirs('learning_data', exist_ok=True)
        
        # 文件路径
        file_path = 'learning_data/signal_history.txt'
        
        # 如果文件不存在，创建一个空文件
        if not os.path.exists(file_path):
            with open(file_path, 'w', encoding='utf-8') as f:
                pass  # 创建空文件
            return signal_history
        
        # 读取文件内容
        with open(file_path, 'r', encoding='utf-8') as f:
            lines = f.readlines()
            
        # 解析每行数据
        for line in lines:
            line = line.strip()
            if line:  # 跳过空行
                try:
                    parts = line.split(',')
                    if len(parts) >= 3:  # 至少包含时间、信号和方向
                        record = {
                            'time': float(parts[0]),  # 时间戳
                            'signals': parts[1],      # 信号组合
                            'score_direction': parts[2],  # 评分方向
                            'current_price': parts[3] if len(parts) > 3 else '0',  # 当前价格
                            'current_volume': parts[4] if len(parts) > 4 else '0',  # 当前成交量
                        }
                        # 如果有RSI值（第5个字段）
                        if len(parts) >= 6:
                            record['rsi'] = parts[5] if parts[5] != 'None' else None
                        else:
                            record['rsi'] = None
                            
                        signal_history.append(record)
                except Exception as e:
                    logging.error(f"解析历史记录行失败: {line}, 错误: {e}")
                    continue
                    
        # 保持最多720条记录（12小时）
        if len(signal_history) > 1500:
            signal_history = signal_history[-1500:]
            
        logging.info(f"成功从文件加载 {len(signal_history)} 条历史记录")
        
    except Exception as e:
        logging.error(f"加载信号历史记录失败: {e}")
        
    return signal_history

def setup_logger():
    logger = logging.getLogger()
    handler = logging.StreamHandler()
    handler.setFormatter(
        logging.Formatter('%(asctime)s %(name)-8s %(levelname)-8s %(message)s [%(filename)s:%(lineno)d]'))
    logger.addHandler(handler)
    logger.setLevel(logging.INFO)
    return logger

def define_options():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--access_token', dest='access_token', required=True,
        help='机器人webhook的access_token from https://open.dingtalk.com/document/orgapp/obtain-the-webhook-address-of-a-custom-robot '
    )
    parser.add_argument(
        '--secret', dest='secret', required=True,
        help='secret from https://open.dingtalk.com/document/orgapp/customize-robot-security-settings#title-7fs-kgs-36x'
    )
    parser.add_argument(
        '--userid', dest='userid',
        help='待 @ 的钉钉用户ID，多个用逗号分隔 from https://open.dingtalk.com/document/orgapp/basic-concepts-beta#title-o8w-yj2-t8x '
    )
    parser.add_argument(
        '--at_mobiles', dest='at_mobiles',
        help='待 @ 的手机号，多个用逗号分隔'
    )
    parser.add_argument(
        '--is_at_all', dest='is_at_all', action='store_true',
        help='是否@所有人，指定则为True，不指定为False'
    )

    return parser.parse_args()

def main():
    global last_at_all_time
    options = define_options()
    # 处理 @用户ID
    at_user_ids = []
    if options.userid:
        at_user_ids = [u.strip() for u in options.userid.split(',') if u.strip()]
    # 处理 @手机号
    at_mobiles = []
    if options.at_mobiles:
        at_mobiles = [m.strip() for m in options.at_mobiles.split(',') if m.strip()]
    
    # 创建分析器实例
    analyzer = CryptoAnalyzer()
    symbol = SYMBOL
    intervals = INTERVALS
    
    # 创建钉钉机器人实例
    dingtalk_robot = DingTalkRobot(options.access_token, options.secret)
    
    # 存储操作建议和回测胜率
    suggestions = []
    win_rates = []
    current_prices = []
    learning_suggestions = []  # 初始化学习系统建议列表
    
    logging.info("开始每分钟发送钉钉消息...")
    try:
        while True:
            # 获取1m时间周期的最新价格和成交量
            def get_latest_price_1m(symbol):
                try:
                    url = f'https://bnapi.bnlex.top/fapi/fapi/v1/klines?symbol={symbol}&interval=1m&limit=1'
                    response = requests.get(url)
                    if response.status_code == 200:
                        kline_data = response.json()
                        if kline_data and len(kline_data) > 0:
                            # 获取最新的K线数据，第4个元素是收盘价，第5个元素是成交量
                            latest_close = kline_data[-1][4]
                            latest_volume = kline_data[-1][5]
                            return str(latest_close), str(latest_volume)
                    return '0', '0'
                except Exception as e:
                    print(f"获取{symbol}的1m价格和成交量失败: {e}")
                    return '0', '0'
            
            # 等待到整分时刻再获取数据
            current_time = time.time()
            sleep_time = 60 - (current_time % 60)
            time.sleep(sleep_time)
            
            # 获取BTCUSDT的1m最新价格和成交量
            latest_price_1m, latest_volume_1m = get_latest_price_1m(SYMBOL)
            
            # 评分系统数据存储
            if 'score_history' not in globals():
                global score_history, signal_history, learning_history
                score_history = []
                # 从文件加载信号历史记录
                signal_history = load_signal_history_from_file()
                learning_history = []  # 存储学习历史记录
            
            # 评分系统直接使用CryptoAnalyzer获取的历史数据，无需记录到price_history
            
            # 评分系统
            def evaluate_score(latest_price_1m):
                # 直接使用CryptoAnalyzer获取的历史数据进行评分
                # 获取BTCUSDT的1分钟历史数据
                historical_1m_data = analyzer.historical_data.get(SYMBOL, {}).get('1m', [])
                
                # 需要至少11条历史数据
                if len(historical_1m_data) < 11:
                    return None
                
                # 初始化评分结果
                result = {
                    'direction': '未知',
                    'position_score': 0,
                    'is_spike': False,
                    'position_desc': '平淡无奇'
                }
                
                # 获取基准价格（第1条数据）
                base_price = historical_1m_data[-11]['close']
                
                # 使用最新获取的价格
                comparison_price = float(latest_price_1m)
                
                # 根据基准价格和比较价格判断方向
                if comparison_price > base_price:
                    result['direction'] = '多'
                elif comparison_price < base_price:
                    result['direction'] = '空'
                
                # 计算位置评分 (0-100)
                direction_count = 0  # 正确方向计数
                wrong_direction_count = 0  # 错误方向计数
                continuous_correct = 0  # 连续正确方向计数
                max_continuous = 0  # 最大连续正确方向计数
                
                # 确定正确的方向（基于基准价格和第10条后的价格）
                correct_direction_up = comparison_price > base_price
                
                # 获取最近10条价格数据
                recent_prices = historical_1m_data[-10:]
                
                # 遍历最近10条数据
                for i, data in enumerate(recent_prices):
                    price = data['close']
                    
                    # 判断当前价格相对于基准价格的方向
                    if (price > base_price and correct_direction_up) or (price < base_price and not correct_direction_up):
                        direction_count += 1
                        continuous_correct += 1
                        max_continuous = max(max_continuous, continuous_correct)
                    else:
                        wrong_direction_count += 1
                        continuous_correct = 0
                
                # 计算位置评分 (0-100)
                # 连续正确方向越多，得分越高
                position_score = min(100, max_continuous * 10)
                
                # 计算价格波动幅度
                # 计算最近10条数据的价格变化
                price_changes = []
                for i in range(1, len(recent_prices)):
                    change = abs(recent_prices[i]['close'] - recent_prices[i-1]['close'])
                    price_changes.append(change)
                
                if price_changes:
                    # 计算平均波动幅度
                    avg_change = sum(price_changes) / len(price_changes)
                    
                    # 如果平均波动幅度较小，则降低位置评分
                    # 这里设定一个阈值，当平均波动幅度小于基准价格的0.1%时，认为波动较小
                    threshold = base_price * 0.001
                    if avg_change < threshold:
                        # 波动越小，评分越低，但不低于0
                        reduction_factor = max(0, avg_change / threshold)
                        position_score *= reduction_factor
                
                result['position_score'] = max(0, position_score)
                
                # 判断是否为插针
                # 插针定义：倒数第2分钟的价格在10分钟前的价格之上，然后最新1分钟在价格之下，或者反过来
                if len(recent_prices) >= 10:
                    # 获取10分钟前的价格（基准价格）
                    base_price = historical_1m_data[-11]['close']
                    # 获取倒数第2分钟的价格
                    second_last_price = recent_prices[8]['close']
                    # 获取最新1分钟的价格
                    latest_price = recent_prices[9]['close']
                    
                    # 判断是否为插针
                    if (second_last_price > base_price and latest_price < base_price) or \
                       (second_last_price < base_price and latest_price > base_price):
                        result['is_spike'] = True
                    else:
                        result['is_spike'] = False
                
                # 根据评分添加形容词（分数越低表示风险越小）
                if result['position_score'] >= 90:
                    result['position_desc'] = '完美无瑕'
                elif result['position_score'] >= 70:
                    result['position_desc'] = '优秀出众'
                elif result['position_score'] >= 50:
                    result['position_desc'] = '良好稳定'
                elif result['position_score'] >= 30:
                    result['position_desc'] = '尚可接受'
                else:
                    result['position_desc'] = '平淡无奇'
                
                return result
            
            # 学习效果评估函数
            def evaluate_learning_effectiveness(analyzer, learning_history):
                """评估学习系统的准确率，分别计算最近1小时和3小时的准确率
                改进版本：放宽时间窗口，处理网络延时和触发间隔问题"""
                if len(learning_history) < 2:
                    return {"1h": {"win": 0, "total": 0}, "3h": {"win": 0, "total": 0}}
                
                # 获取当前时间
                current_time = time.time()
                
                # 初始化结果
                results = {"1h": {"win": 0, "total": 0}, "3h": {"win": 0, "total": 0}}
                
                # 遍历学习历史记录
                for i in range(len(learning_history)):
                    current_prediction = learning_history[i]['most_common_direction']
                    
                    # 获取信号组生成的时间
                    signal_time = learning_history[i]['signal_time']
                    # 确保时间是数字类型（时间戳）
                    if not isinstance(signal_time, (int, float)):
                        logging.error(f"时间格式错误: {signal_time} 不是时间戳类型")
                        continue
                    
                    # 检查是否已经过去了至少8分钟，以便验证预测（降低到8分钟以增加验证机会）
                    if current_time - signal_time < 480:  # 480秒 = 8分钟
                        continue  # 还没有足够的时间来验证这个预测
                    
                    # 查找8-12分钟后的记录（放宽时间窗口到8-12分钟）
                    target_time_min = signal_time + 480   # 8分钟后
                    target_time_max = signal_time + 720   # 12分钟后
                    matching_record = None
                    min_time_diff = float('inf')
                    
                    # 在历史记录中查找最接近8-12分钟后的记录
                    for record in learning_history:
                        record_time = record['signal_time']
                        # 检查记录是否在目标时间窗口内
                        if target_time_min <= record_time <= target_time_max:
                            time_diff = abs(record_time - signal_time - 600)  # 与理想10分钟的时间差
                            if time_diff < min_time_diff:
                                min_time_diff = time_diff
                                matching_record = record
                    
                    # 如果找到了匹配的记录，则计算准确率
                    if matching_record is not None:
                        # 获取记录时的价格
                        current_price = float(learning_history[i]['current_price'])
                        
                        # 获取验证时间点的价格
                        validation_price = float(matching_record['current_price'])
                        
                        # 计算实际价格变化方向
                        if validation_price > current_price:
                            actual_direction = '多'
                        elif validation_price < current_price:
                            actual_direction = '空'
                        else:
                            actual_direction = '无'
                        
                        # 计算时间差
                        time_diff_hours = (current_time - signal_time) / 3600
                        
                        # 如果当前预测与实际价格变化方向一致，则认为预测正确
                        is_correct = current_prediction == actual_direction
                        
                        # 更新1小时和3小时的统计
                        if time_diff_hours <= 1:  # 最近1小时
                            results["1h"]["total"] += 1
                            if is_correct:
                                results["1h"]["win"] += 1
                        if time_diff_hours <= 3:  # 最近3小时
                            results["3h"]["total"] += 1
                            if is_correct:
                                results["3h"]["win"] += 1
                    else:
                        # 如果没有找到匹配记录，记录日志用于调试
                        logging.debug(f"未找到匹配记录：信号时间 {signal_time}, 目标窗口 {target_time_min}-{target_time_max}")
                
                # 添加统计信息日志
                total_1h = results["1h"]["total"]
                total_3h = results["3h"]["total"]
                if total_1h > 0:
                    accuracy_1h = (results["1h"]["win"] / total_1h) * 100
                    logging.info(f"1小时准确率统计：{accuracy_1h:.1f}% ({results['1h']['win']}/{total_1h})")
                if total_3h > 0:
                    accuracy_3h = (results["3h"]["win"] / total_3h) * 100
                    logging.info(f"3小时准确率统计：{accuracy_3h:.1f}% ({results['3h']['win']}/{total_3h})")
                
                return results
            
            # 获取评分结果
            score_result = evaluate_score(latest_price_1m)
            
            # 学习系统：
            
            def save_signal_to_file(signal_record):
                """将信号记录保存到txt文件中"""
                try:
                    # 确保目录存在
                    os.makedirs('learning_data', exist_ok=True)
                    
                    # 文件路径
                    file_path = 'learning_data/signal_history.txt'
                    
                    # 以追加模式写入文件
                    with open(file_path, 'a', encoding='utf-8') as f:
                        rsi_value = signal_record.get('rsi', 'None')
                        if rsi_value is None:
                            rsi_value = 'None'
                        f.write(f"{signal_record['time']},{signal_record['signals']},{signal_record['score_direction']},{signal_record['current_price']},{signal_record['current_volume']},{rsi_value}\n")
                except Exception as e:
                    logging.error(f"保存信号到文件失败: {e}")

            #分析学习信号函数
    
             # 该函数用于分析学习建议中的信号，提取有价值的学习模式和趋势，
            # 为后续的学习优化提供数据支持。

            def analyze_learning_signals(learning_suggestions):
                if len(learning_suggestions) >= 5:  # 需要至少5个信号（一组完整的5位信号）
                    # 获取当前信号组，最新添加的5个元素是新的
                    current_group = ''.join(str(s) for s in learning_suggestions[-5:])
                    
                    # 打印调试信息
                    logging.info(f"learning_suggestions列表内容: {learning_suggestions}")
                    logging.info(f"current_group: {current_group}")
                    
                    # 计算1分钟RSI
                    rsi_value = None
                    historical_1m_data = analyzer.historical_data.get(SYMBOL, {}).get('1m', [])
                    if len(historical_1m_data) >= 14:  # RSI需要至少14个数据点
                        rsi_values = analyzer.calculate_rsi(historical_1m_data, 14)
                        if rsi_values[-1] is not None:
                            rsi_value = rsi_values[-1]
                    
                    # 记录信号历史
                    signal_record = {
                        'time': time.time(),  # 使用时间戳格式
                        'signals': current_group,
                        'score_direction': score_result['direction'] if score_result else '未知',  # 保存评分方向(10分前的)
                        'current_price': latest_price_1m,  # 保存当前价格
                        'current_volume': latest_volume_1m,  # 保存当前成交量
                        'rsi': rsi_value  # 保存RSI值
                    }
                    
                    signal_history.append(signal_record)
                    
                    # 保存到文件
                    save_signal_to_file(signal_record)
                    
                    # 保持最多720条信号历史记录（12小时）
                    if len(signal_history) > 1500:
                        signal_history.pop(0)
                    
                    # 分析历史记录，统计不同信号组合对应的评分方向
                    direction_stats = {}
                    # 计算时间衰减因子
                    current_time = time.time()
                    
                    # 对于当前最新的记录，查找10分钟前的记录来建立对应关系
                    current_record = signal_record
                    current_time_stamp = current_record['time']
                    
                    # 查找8-12分钟前的记录（放宽时间窗口处理网络延时）
                    target_time_min = current_time_stamp - 720  # 12分钟前的时间戳
                    target_time_max = current_time_stamp - 480  # 8分钟前的时间戳
                    
                    matching_record = None
                    min_time_diff = float('inf')
                    
                    # 在历史记录中查找最接近8-12分钟前的记录
                    for record in signal_history[:-1]:  # 排除当前最新记录
                        record_time = record['time']
                        # 检查记录是否在目标时间窗口内
                        if target_time_min <= record_time <= target_time_max:
                            time_diff = abs(record_time - (current_time_stamp - 600))  # 与理想10分钟的时间差
                            if time_diff < min_time_diff:
                                min_time_diff = time_diff
                                matching_record = record
                    
                    # 记录查找结果用于调试
                    if matching_record is None:
                        logging.debug(f"未找到匹配的10分钟前记录：当前时间 {current_time_stamp}, 目标窗口 {target_time_min}-{target_time_max}")
                    
                    # 如果找到了匹配的记录，则建立对应关系
                    if matching_record is not None:
                        # 获取10分钟前的价格
                        ten_min_price = float(matching_record['current_price'])
                        # 获取当前价格
                        current_price = float(current_record['current_price'])
                        # 计算实际价格变化方向
                        if ten_min_price > current_price:
                            result_direction = '多'
                        elif ten_min_price < current_price:
                            result_direction = '空'
                        else:
                            result_direction = '无'
                        
                        signals = matching_record['signals']
                        
                        # 计算时间差（小时）
                        time_diff_hours = (current_time - matching_record['time']) / 3600
                        
                        # 计算时间衰减因子（最近的数据权重更高）
                        # 使用指数衰减函数，最近1小时内权重为1，12小时前权重约为0.3
                        decay_factor = math.exp(-time_diff_hours / 12)
                        
                        if signals not in direction_stats:
                            direction_stats[signals] = {'多': 0, '空': 0}
                        
                        if result_direction in direction_stats[signals]:
                            # 应用时间衰减因子
                            direction_stats[signals][result_direction] += decay_factor
                    
                    # 找到当前信号组合的历史统计，按RSI区间分类
                    best_match_stats = None
                    
                    # 按RSI区间分类统计：超买(RSI>70)、中性(30≤RSI≤70)、超卖(RSI<30)
                    rsi_category_stats = {
                        'overbought': {'多': 0, '空': 0},  # RSI>70
                        'neutral': {'多': 0, '空': 0},     # 30≤RSI≤70
                        'oversold': {'多': 0, '空': 0}     # RSI<30
                    }
                    rsi_category_counts = {
                        'overbought': 0,
                        'neutral': 0,
                        'oversold': 0
                    }
                    
                    # 遍历所有记录，为每条记录查找其10分钟前的记录
                    for i in range(len(signal_history)):
                        current_rec = signal_history[i]
                        # 只处理相对较新的记录，确保有足够的历史记录可以查找
                        if i >= 10:  # 至少需要10条记录才能查找10分钟前的数据
                            # 查找10分钟前的记录
                            target_time = current_rec['time'] - 600
                            matching_rec = None
                            min_diff = float('inf')
                            
                            # 在当前记录之前的记录中查找
                            for j in range(i):
                                time_diff = abs(signal_history[j]['time'] - target_time)
                                if 540 <= (current_rec['time'] - signal_history[j]['time']) <= 660 and time_diff < min_diff:
                                    min_diff = time_diff
                                    matching_rec = signal_history[j]
                            
                            # 如果找到了匹配记录，并且信号完全匹配
                            if matching_rec is not None and matching_rec['signals'] == current_group:  # 完全匹配而不是聚类匹配
                                # 计算价格变化方向
                                ten_min_price = float(matching_rec['current_price'])
                                current_price = float(current_rec['current_price'])
                                if ten_min_price > current_price:
                                    result_direction = '多'
                                elif ten_min_price < current_price:
                                    result_direction = '空'
                                else:
                                    result_direction = '无'
                                
                                time_diff_hours = (current_time - matching_rec['time']) / 3600
                                decay_factor = math.exp(-time_diff_hours / 12)
                                
                                # 根据匹配记录的RSI值分类统计
                                rsi_value = matching_rec.get('rsi')
                                if rsi_value is not None:
                                    try:
                                        rsi_float = float(rsi_value)
                                        if rsi_float > 70:
                                            category = 'overbought'
                                        elif rsi_float >= 30:
                                            category = 'neutral'
                                        else:
                                            category = 'oversold'
                                        
                                        if result_direction in rsi_category_stats[category]:
                                            rsi_category_stats[category][result_direction] += decay_factor
                                            rsi_category_counts[category] += decay_factor
                                    except (ValueError, TypeError):
                                        # RSI值转换失败，跳过此记录
                                        continue
                    
                    # 获取当前RSI值以确定使用哪个区间的统计
                    current_rsi_category = None
                    if rsi_value is not None:
                        try:
                            rsi_float = float(rsi_value)
                            if rsi_float > 70:
                                current_rsi_category = 'overbought'
                            elif rsi_float >= 30:
                                current_rsi_category = 'neutral'
                            else:
                                current_rsi_category = 'oversold'
                        except (ValueError, TypeError):
                            current_rsi_category = None
                    
                    # 优先使用当前RSI区间的统计，如果没有则使用所有区间的合并统计
                    if current_rsi_category is not None and rsi_category_counts[current_rsi_category] > 0:
                        best_match_stats = rsi_category_stats[current_rsi_category]
                        exact_count = rsi_category_counts[current_rsi_category]
                    else:
                        # 合并所有RSI区间的统计
                        combined_stats = {'多': 0, '空': 0}
                        combined_count = 0
                        for category in rsi_category_stats:
                            for direction in ['多', '空']:
                                combined_stats[direction] += rsi_category_stats[category][direction]
                            combined_count += rsi_category_counts[category]
                        
                        if combined_count > 0:
                            best_match_stats = combined_stats
                            exact_count = combined_count
                    
                    # 初始化返回值
                    most_common_direction = None
                    total_count = 0
                    
                    if best_match_stats is not None:
                        # 计算各方向的百分比
                        direction_percentages = {}
                        total_sum = sum(best_match_stats.values())
                        if total_sum > 0:
                            for direction, count in best_match_stats.items():
                                direction_percentages[direction] = (count / total_sum) * 100
                        
                        # 检查是否有一方大于70%
                        max_direction = max(direction_percentages, key=direction_percentages.get) if direction_percentages else None
                        max_percentage = direction_percentages[max_direction] if max_direction else 0
                        
                        # RSI区间统计判断机制：
                        # 1. 基于当前RSI值对应区间的历史统计数据判断多空方向
                        # 2. 当统计结果显示多空方向不明确时（最高方向<65%），使用RSI值进一步细分判断
                        if max_percentage >= 65:  # 统计结果明确，采用统计判断
                            # 找出出现次数最多的评分方向
                            most_common_direction = max_direction
                        else:
                            # 统计不明确，使用RSI值进一步细分判断
                            if rsi_value is not None:
                                try:
                                    rsi_float = float(rsi_value)
                                    # 简化RSI细分判断逻辑
                                    if rsi_float > 70:  # 超买区域
                                        most_common_direction = '空'
                                    elif rsi_float < 30:  # 超卖区域
                                        most_common_direction = '多'
                                    else:  # 中性区域
                                        most_common_direction = '等'  # 中性区域建议等待
                                except (ValueError, TypeError):
                                    most_common_direction = '等'  # RSI值无效，建议等待
                            else:
                                most_common_direction = '等'  # 无法计算RSI，建议等待
                        
                        total_count = sum(best_match_stats.values())
                        
                        # 只有当方向不是"等"时才记录学习结果
                        if most_common_direction != '等':
                            # 记录学习结果，包括判断依据
                            learning_record = {
                                'signals': current_group,
                                'most_common_direction': most_common_direction,
                                'stats': best_match_stats,
                                'total_count': total_count,
                                'time': time.time(),  # 记录添加时间（时间戳格式）
                                'signal_time': time.time(),  # 信号组生成时间（时间戳格式）
                                'current_price': latest_price_1m,  # 记录当前价格
                                'current_volume': latest_volume_1m,  # 记录当前成交量
                                'rsi': rsi_value,  # 保存RSI值
                                'based_on': 'statistics' if max_percentage >= 65 else 'rsi'  # 记录判断依据：统计结果或RSI判断
                            }
                            learning_history.append(learning_record)
                        else:
                            # 当方向为"等"时，不记录学习结果
                            pass
                    
                # 保持最多1550条学习记录
                if len(learning_history) > 1500:
                    learning_history.pop(0)
                
                return most_common_direction, best_match_stats, total_count, learning_history
            # 基于成交量变化的信号强度评估
            def evaluate_signal_strength(avg_volume, current_volume):
                """评估信号强度，基于近期平均成交量和当前成交量的动态判断"""
                # 计算动态阈值，基于近期平均成交量
                # 当前成交量相对于平均成交量的变化倍数
                if avg_volume != 0:
                    volume_ratio = current_volume / avg_volume
                else:
                    volume_ratio = 1
                
                # 根据成交量倍数动态判断信号强度
                if volume_ratio >= SIGNAL_STRENGTH_THRESHOLDS['STRONG']:  # 成交量是平均值的2倍及以上
                    return "强烈"
                elif volume_ratio >= SIGNAL_STRENGTH_THRESHOLDS['MEDIUM']:  # 成交量是平均值的1.5倍及以上
                    return "较强"
                elif volume_ratio >= SIGNAL_STRENGTH_THRESHOLDS['WEAK']:  # 成交量是平均值的1.1倍及以上
                    return "一般"
                else:
                    return "较弱"
            
            # 存储历史数据的字典
            if 'historical_analysis_data' not in globals():
                global historical_analysis_data
                historical_analysis_data = {}
            
            # 获取每个时间间隔的数据
            for interval in intervals:
                # 检查是否已有历史数据
                cache_key = f"{symbol}_{interval}"
                current_timestamp = time.time()
                
                # 如果有缓存数据且时间间隔小于55秒，则使用缓存数据
                if cache_key in historical_analysis_data:
                    cached_time, cached_results = historical_analysis_data[cache_key]
                    if current_timestamp - cached_time < 55:  # 55秒内使用缓存
                        results = cached_results
                    else:
                        # 运行异步分析
                        results = asyncio.run(analyzer.start_analysis(interval))
                        # 更新缓存
                        historical_analysis_data[cache_key] = (current_timestamp, results)
                else:
                    # 运行异步分析
                    results = asyncio.run(analyzer.start_analysis(interval))
                    # 更新缓存
                    historical_analysis_data[cache_key] = (current_timestamp, results)
                
                # 查找BTCUSDT的结果
                for result in results:
                    if SYMBOL in result:
                        # 提取操作建议
                        if '买入' in result:
                            suggestions.append('1')  # 买入
                        elif '卖出' in result:
                            suggestions.append('0')  # 卖出
                        else:
                            suggestions.append('0')  # 空
                        

                        
                        # 提取回测胜率
                        import re
                        win_rate_match = re.search(r'回测胜率\s*(\d+)%', result)
                        if win_rate_match:
                            win_rates.append(win_rate_match.group(1))
                        else:
                            win_rates.append('0')
                        
                        # 限制win_rates列表长度，保持最多20条记录
                        if len(win_rates) > 20:
                            win_rates = win_rates[-20:]  # 保留最后20个元素，移除旧的元素
                        
                        # 提取当前价格
                        price_match = re.search(r'当前价格\s*\$([\d\.]+)', result)
                        if price_match:
                            current_prices.append(price_match.group(1))
                        else:
                            current_prices.append('0')
                        
                        # 限制current_prices列表长度，保持最多20条记录
                        if len(current_prices) > 20:
                            current_prices = current_prices[-20:]  # 保留最后20个元素，移除旧的元素
                        break
            
            # 将当前信号添加到学习系统分析列表
            learning_suggestions.extend(suggestions)
            
            # 限制学习建议列表长度，保持最多20条记录
            if len(learning_suggestions) > 20:
                learning_suggestions = learning_suggestions[-20:]
            
            # 执行学习系统分析
            learning_direction, learning_stats, learning_count, learning_history = analyze_learning_signals(learning_suggestions)
            print("---------------",suggestions)
            

            
            # 格式化消息
            if len(suggestions) >= 5 and len(win_rates) >= 5:
                # 按用户要求格式化：买入/卖出/观望分别转换为1/0/0，与对应回测胜率组合
                # 例如：10001,44 50 47 55 60
                suggestions_str = ''.join(str(s) for s in suggestions[:5])  # 确保操作建议为字符串并取前五个
                win_rates_str = ' '.join(win_rates[:5])  # 五个时间间隔的回测胜率
                current_time = time.strftime("%Y-%m-%d %H:%M:%S")  # 获取当前时间
                # --清空这个数据
                suggestions = []

                # 添加评分信息到消息
                if score_result:
                    # 计算10分钟前的时间
                    ten_minutes_ago = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time() - 600))
                    
                    # 获取10分钟前的价格
                    ten_min_ago_price = 'N/A'
                    current_price = 'N/A'
                    historical_1m_data = analyzer.historical_data.get(SYMBOL, {}).get('1m', [])
                    if len(historical_1m_data) >= 10:
                        # 获取10分钟前的价格（数组倒数第10个元素）
                        ten_min_ago_price = historical_1m_data[-10]['close']
                        # 获取当前价格（使用上面获取到的最新价格）
                        current_price = latest_price_1m
                   
                    # 计算1分钟RSI
                    rsi_value = 'N/A'
                    if len(historical_1m_data) >= 14:  # RSI需要至少14个数据点
                        rsi_values = analyzer.calculate_rsi(historical_1m_data, 14)
                        if rsi_values[-1] is not None:
                            rsi_value = f"{rsi_values[-1]:.2f}"
                    
                    # 构建评分信息
                    score_info = f"\n{ten_minutes_ago}你应该（{score_result['direction']}）\n10分钟前价格：{ten_min_ago_price}\n当前价格：{current_price}\n位置评分：{score_result['position_score']}/100,{score_result['position_desc']}\n是否插针：{'是' if score_result['is_spike'] else '否'}\nRSI(14): {rsi_value}"
                else:
                    score_info = "\n评分系统：数据不足，等待更多数据..."
                
                # 添加学习系统信息到消息
                learning_info = ""
                # 确保rsi_value变量被初始化
                rsi_value = None
                # 获取当前RSI值用于消息显示
                historical_1m_data = analyzer.historical_data.get(SYMBOL, {}).get('1m', [])
                if len(historical_1m_data) >= 14:  # RSI需要至少14个数据点
                    rsi_values = analyzer.calculate_rsi(historical_1m_data, 14)
                    if rsi_values[-1] is not None:
                        rsi_value = f"{rsi_values[-1]:.2f}"
                if learning_direction and learning_stats and learning_count > 0:
                    # 计算各方向的百分比
                    direction_percentages = {}
                    for direction, count in learning_stats.items():
                        direction_percentages[direction] = round((count / learning_count) * 100, 1)
                    
                    # 构建学习系统信息
                    learning_info = f"\n学习系统分析：\n当信号为 {suggestions_str} 时，历史数据显示:\n"
                    learning_info += f"  多: {learning_stats['多']}次 ({direction_percentages.get('多', 0):.1f}%)\n"
                    learning_info += f"  空: {learning_stats['空']}次 ({direction_percentages.get('空', 0):.1f}%)\n"
                    
                    # 显示当前使用的RSI区间统计信息
                    if 'current_rsi_category' in locals() and current_rsi_category is not None:
                        category_names = {
                            'overbought': '超买区间(RSI>70)',
                            'neutral': '中性区间(30≤RSI≤70)',
                            'oversold': '超卖区间(RSI<30)'
                        }
                        learning_info += f"\n当前使用{category_names[current_rsi_category]}的历史统计数据进行判断。"
                    else:
                        learning_info += f"\n当前使用所有RSI区间的合并统计数据进行判断。"
                    
                    # 检查是否需要RSI辅助判断
                    max_direction = max(direction_percentages, key=direction_percentages.get) if direction_percentages else None
                    max_percentage = direction_percentages[max_direction] if max_direction else 0
                    
                    # RSI区间统计判断机制说明
                    if max_percentage >= 65:
                        learning_info += f"\n✓ 基于RSI区间的统计结果明确（{max_direction}方向占{max_percentage:.1f}%），采用统计判断。"
                    else:
                        learning_info += f"\n⚠ RSI区间统计不明确（最高仅{max_percentage:.1f}%），使用RSI值进一步判断。"
                        
                        # 根据RSI值提供进一步的建议
                        if rsi_value is not None:
                            try:
                                rsi_float = float(rsi_value)
                                if rsi_float > 70:
                                    learning_info += f"\nRSI(14)值为 {rsi_float:.2f}，处于超买区域，建议做空。"
                                elif rsi_float < 30:
                                    learning_info += f"\nRSI(14)值为 {rsi_float:.2f}，处于超卖区域，建议做多。"
                                else:
                                    learning_info += f"\nRSI(14)值为 {rsi_float:.2f}，处于中性区域，建议等待。"
                            except (ValueError, TypeError):
                                learning_info += f"\nRSI值无效，建议等待。"
                        else:
                            learning_info += f"\n无法计算RSI值，请等待更多数据。"
                    
                    # 添加学习效果评估
                    learning_accuracy = evaluate_learning_effectiveness(analyzer, learning_history)
                    if learning_accuracy["1h"]["total"] > 0 or learning_accuracy["3h"]["total"] > 0:
                        learning_info += f"\n学习系统准确率:"
                        if learning_accuracy["1h"]["total"] > 0:
                            accuracy_1h = (learning_accuracy['1h']['win'] / learning_accuracy['1h']['total']) * 100
                            learning_info += f"\n  1小时: {accuracy_1h:.1f}% ({learning_accuracy['1h']['win']}/{learning_accuracy['1h']['total']})"
                        if learning_accuracy["3h"]["total"] > 0:
                            accuracy_3h = (learning_accuracy['3h']['win'] / learning_accuracy['3h']['total']) * 100
                            learning_info += f"\n  3小时: {accuracy_3h:.1f}% ({learning_accuracy['3h']['win']}/{learning_accuracy['3h']['total']})"
                    
                    # 添加信号强度评估
                    # 计算价格变化百分比
                    try:
                        price_change_percent = 0
                        if float(latest_price_1m) != 0:
                            price_change_percent = ((float(latest_price_1m) - float(ten_min_ago_price)) / float(ten_min_ago_price)) * 100
                        
                        # 获取历史成交量数据用于计算平均值
                        historical_1m_data = analyzer.historical_data.get(SYMBOL, {}).get('1m', [])
                        avg_volume = 0
                        if len(historical_1m_data) >= 10:
                            # 计算最近10个周期的平均成交量
                            total_volume = sum([float(kline['volume']) for kline in historical_1m_data[-10:]])
                            avg_volume = total_volume / 10
                        
                        # 评估信号强度（基于近期平均成交量和当前成交量的动态判断）
                        signal_strength = evaluate_signal_strength(avg_volume, float(latest_volume_1m))
                        # 计算成交量变化百分比用于显示
                        volume_change_percent = 0
                        if avg_volume != 0:
                            volume_change_percent = ((float(latest_volume_1m) - avg_volume) / avg_volume) * 100
                        learning_info += f"\n信号强度: {signal_strength} (成交量变化: {volume_change_percent:.2f}%)"
                    except Exception as e:
                        logging.error(f"计算信号强度时出错: {e}")
                        learning_info += f"\n信号强度: 无法计算"
                    
                    # 获取判断依据（基于RSI区间统计判断）
                    judgment_basis = "统计判断"
                    if learning_history and len(learning_history) > 0:
                        latest_record = learning_history[-1]  # 获取最新的学习记录
                        if 'based_on' in latest_record:
                            if latest_record['based_on'] == 'statistics':
                                judgment_basis = "统计判断"
                            elif latest_record['based_on'] == 'rsi':
                                judgment_basis = "RSI判断"
                    
                    # 添加还没有10分钟结束的仓位信息
                    current_time = time.time()
                    open_positions = []
                    for record in learning_history:
                        if 'signal_time' in record and 'most_common_direction' in record:
                            time_elapsed = current_time - record['signal_time']
                            if time_elapsed < 600:  # 还没有超过10分钟
                                minutes_elapsed = int(time_elapsed / 60)
                                direction = record['most_common_direction']
                                if direction in ['多', '空']:  # 只显示有效的开仓方向
                                    open_positions.append(f"{direction}仓({minutes_elapsed}分钟前)")
                    
                    if open_positions:
                        positions_info = f"\n未结束仓位：{', '.join(open_positions)}"
                    else:
                        positions_info = "\n当前无未结束仓位"
                    
                    learning_info += f"\n根据历史统计，此时你应该（{learning_direction}）- 判断依据：{judgment_basis}{positions_info}"
                else:
                    learning_info = "\n学习系统：数据不足，等待更多数据..."
                
                current_msg = f'{symbol}: {suggestions_str},{win_rates_str} | 1m价格: {latest_price_1m} | 1m成交量: {latest_volume_1m} | 时间: {current_time}{score_info}{learning_info}'
            else:
                current_msg = f'{symbol}: 无法获取完整分析数据 - {time.strftime("%Y-%m-%d %H:%M:%S")}'
            
            # 检查是否需要@所有人
            should_at_all = False
            if suggestions_str == '11111' or suggestions_str == '00000':
                # 检查距离上次@所有人的时间是否超过5分钟
                current_time = time.time()
                if current_time - last_at_all_time > 300:  # 300秒 = 5分钟
                    should_at_all = True
                    last_at_all_time = current_time  # 更新最后一次@所有人的时间
            
            # 发送消息
            # 清空suggestions列表，为下一轮循环做准备
            suggestions.clear()
            
            dingtalk_robot.send_message(
                current_msg,  # 移除了交易信息
                at_user_ids=at_user_ids,
                at_mobiles=at_mobiles,
                is_at_all=options.is_at_all or should_at_all  # 如果命令行参数指定了@所有人，或者满足条件需要@所有人
            )
            # 不需要额外等待，下次循环会自动等到整分
            logging.info("消息发送成功，等待下一次整分...")
    except KeyboardInterrupt:
        logging.info("程序已停止")


if __name__ == '__main__':
    setup_logger()  # 初始化日志
    main()